package sk.velkavrana.app.util;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.sql.Types;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: mtymes
 * Date: Feb 18, 2009
 * Time: 4:30:32 PM
 */
public class ImportUtil {

    public static Document getDocument(String filename) {
        Document document = null;
        SAXReader reader = new SAXReader();

        try {
            document = reader.read(new FileReader(filename));
        } catch (DocumentException e) {
            e.printStackTrace();
            document = null;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            document = null;
        }

        return document;
    }


    public static Map<String, Integer> getColTypes(Element tableInfo) {
        Map<String, Integer> returnValue = new HashMap<String, Integer>();

        for (Element colInfo : (List<Element>) tableInfo.selectNodes("colinfo")) {
            String name = colInfo.attribute("name").getValue();
            Integer sqlType = new Integer(colInfo.attribute("sqltype").getValue());

            returnValue.put(name, sqlType);
        }

        return returnValue;
    }


    public static Map<String, Object> getRowData(Element row, Map<String, Integer> colTypes) {
        Map<String, Object> returnValue = new HashMap<String, Object>();

        for (Element column : (List<Element>) row.selectNodes("column")) {
            String name = column.attribute("name").getValue();
            String stringValue = column.getText();
            Object value = null;

            Attribute isnull = column.attribute("isnull");
            if (isnull == null || !"true".equalsIgnoreCase(isnull.getValue())) {
                value = convertToDbType(stringValue, colTypes.get(name));
            }

            returnValue.put(name, value);
        }

        return returnValue;
    }


    private static DateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss.S");
    private static DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");


    private static Object convertToDbType(String value, Integer type) {
        Object returnValue = null;

        if (value != null && type != null) {
            // todo: implement
            long time;

            switch (type) {
                case Types.BIT: // -7;
                    // todo: test this
                    returnValue = value;
                    break;
                case Types.LONGVARCHAR: // -1
                    // todo: test this
                    returnValue = value;
                    break;
                case Types.CHAR: // 1
                    returnValue = value;
                    break;
                case Types.NUMERIC: // 2
                    returnValue = new BigDecimal(value);
                    break;
                case Types.DECIMAL: // 3
                    returnValue = new BigDecimal(value);
                    break;
                case Types.INTEGER: // 4
                    returnValue = new Integer(value);
                    break;
                case Types.SMALLINT: // 5
                    returnValue = new Short(value);
                    break;
                case Types.FLOAT: // 6
                    returnValue = new Double(value);
                    break;
                case Types.REAL: // 7
                    returnValue = new Float(value);
                    break;
                case Types.DOUBLE: // 8
                    returnValue = new Double(value);
                    break;
                case Types.VARCHAR: // 12
                    returnValue = value;
                    break;
                case Types.DATE: // 91
                    try {
                        time = dateFormatter.parse(value).getTime();
                    } catch (ParseException e) {
                        e.printStackTrace();
                        time = new Date().getTime();
                    }
                    returnValue = new java.sql.Date(time);
                    break;
                case Types.TIME: // 92
                    // todo: test
                    try {
                        time = timeFormatter.parse(value).getTime();
                    } catch (ParseException e) {
                        try {
                            time = dateFormatter.parse(value).getTime();
                        } catch (ParseException e1) {
                            e1.printStackTrace();
                            time = new Date().getTime();
                        }
                    }
                    returnValue = new java.sql.Time(time);
                    break;
                case Types.TIMESTAMP: // 93
                    try {
//                        time = timeFormatter.parse(value).getTime();
                        time = dateFormatter.parse(value).getTime();
                    } catch (ParseException e) {
                        e.printStackTrace();
                        time = new Date().getTime();
                    }
                    returnValue = new java.sql.Timestamp(time);
                    break;
                case Types.CLOB: // 2005
                    // todo: test
//                    returnValue = new StringReader(value);
                    returnValue = new StringReader(value);
                    break;
                default:
                    // todo: change the error signature
                    throw new UnsupportedOperationException("can't parse value of type " + type);

            }
        }

        return returnValue;
    }
}
